package edu.hawaii.myisern.model;

import java.io.File;
import java.io.FileWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import edu.hawaii.myisern.collaborations.jaxb.Collaboration;
import edu.hawaii.myisern.collaborations.jaxb.Collaborations;
import edu.hawaii.myisern.collaborations.jaxb.CollaboratingOrganizations;
import edu.hawaii.myisern.collaborations.jaxb.CollaborationTypes;
import edu.hawaii.myisern.collaborations.jaxb.Years;
import edu.hawaii.myisern.collaborations.jaxb.OutcomeTypes;
import java.math.BigInteger;

/**
 * Wrapper class to hold information about Collaborations.
 * 
 * @author Andrew Wong
 *
 */
public class CollaborationData implements DisplayableIsernData {

  private JAXBContext collaborationsJaxbContext;
  private Collaborations collaborations;
  
  
  /**
   * Retrieves the Collaborations object stored within.  Used for semantic checking.
   * 
   * @return Instance of Collaborations object.
   */
  Collaborations getCollaborations() {
    return this.collaborations;
  }
  
  /**
   * Retrieves the data stored in the object.
   * 
   * @return A list of objects in String representation, 
   * entries corresponding to the header entries.
   */
  @Override
  public List<List<String>> getData() {
    List<List<String>> result = new ArrayList<List<String>>();
    
    for (Collaboration item : this.collaborations.getCollaboration()) {
      List<String> entry = new ArrayList<String>();
      
      entry.add(MyIsernModel.nullToEmpty(item.getName()));
      entry.add(MyIsernModel.nullToEmpty(item.getCollaboratingOrganizations().
          getCollaboratingOrganization().toString()));
      entry.add(MyIsernModel.nullToEmpty(
          item.getCollaborationTypes().getCollaborationType().toString()));
      entry.add(MyIsernModel.nullToEmpty(item.getYears().getYear().toString()));
      entry.add(MyIsernModel.nullToEmpty(item.getOutcomeTypes().getOutcomeType().toString()));
      entry.add(MyIsernModel.nullToEmpty(item.getDescription()));
      
      result.add(entry);
    }
   
    return result;
  }

  /**
   * Retrieves the field names for the data that is returned.
   * 
   * @return Field names in a list.
   */
  @Override
  public List<String> getHeader() {
    List<String> result = new ArrayList<String>();
    result.add("Name");
    result.add("Collaborating Organizations");
    result.add("Collaboration Types");
    result.add("Years");
    result.add("Outcome Types");
    result.add("Description");

    return result;
  }

  /**
   * Loads data from XML file.  If baseDir does not exist, it creates
   * an empty data set.
   * 
   * @param baseDir Directory to load data from.
   * @return true if data is loaded successful, false if data load failed.
   */
  public boolean loadData(String baseDir) {
    try {
      // Now do it once more for the collaborations. 
      this.collaborationsJaxbContext = 
        JAXBContext.newInstance("edu.hawaii.myisern.collaborations.jaxb");
      File researchersFile = new File(baseDir + "collaborations.xml");
      Unmarshaller unmarshaller = this.collaborationsJaxbContext.createUnmarshaller();
      this.collaborations = (Collaborations) unmarshaller.unmarshal(researchersFile);
    }
    catch (Exception e) {
      Collaboration foo = new Collaboration();
      foo.setName(e.toString());
      
      collaborations = new Collaborations();
      collaborations.getCollaboration().add(foo);
      
      foo = new Collaboration();
      foo.setName(baseDir + "/collaborations.xml");
      collaborations.getCollaboration().add(foo);
    }
    
    return true;
  }

  /**
   * Saves data to an XML file.
   * 
   * @param baseDir Directory to save files to.
   * @return true if successful.
   */
  public boolean saveData(String baseDir) {
    Marshaller marshaller;
    try {
      marshaller = this.collaborationsJaxbContext.createMarshaller();
      StringWriter writer = new StringWriter();
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT , Boolean.TRUE);
      marshaller.marshal(this.collaborations, writer);
      
      FileWriter researcherFile = new FileWriter(baseDir + "collaborations.xml");
      researcherFile.write(writer.toString());
      researcherFile.close();


      return true;
    }
    catch (Exception e) {
      e.printStackTrace();
      
      return false;
    }
  }


  /**
   * Updates or creates the array containing the row that was edited or added.
   * @param newEntry contains the edited/added entry.
   * @param toAdd true if is a new added entry.
   * @return String containing error message, if any.
   */
  @Override
  public String updateData(List<String> newEntry, boolean toAdd) {
    // find the entry first
    Collaboration target = null;
    CollaboratingOrganizations tempCollabOrgs = new CollaboratingOrganizations();
    CollaborationTypes tempCollabTypes = new CollaborationTypes();
    Years tempYears = new Years();
    OutcomeTypes tempOutcome = new OutcomeTypes();
    List<String> tempList;
    
    // initialize possible empty lists
    tempYears.getYear();
    tempOutcome.getOutcomeType();
    tempCollabTypes.getCollaborationType();
    tempCollabOrgs.getCollaboratingOrganization();
    
    
    for (Collaboration item : this.collaborations.getCollaboration()) {
      if (newEntry.get(0).trim().equals(item.getName())) {
        target = item;
      }
    }
    
    if (target == null && toAdd) {
      target = new Collaboration();
      this.collaborations.getCollaboration().add(target);
    }
    else if (target != null && toAdd) {
      return " Collaboration " + newEntry.get(0) + " already exists.";
    }
    else if (target == null && !toAdd) {
      return " Collaboration " + newEntry.get(0) + " does not exist, cannot edit.";
    }
    
    //    result.add("Name");
    target.setName(newEntry.get(0).trim());
    
    //    result.add("Organization");
    tempList = MyIsernModel.stringToArray(newEntry.get(1).trim());
    for (String item : tempList) {
      tempCollabOrgs.getCollaboratingOrganization().add(item);
    }
    target.setCollaboratingOrganizations(tempCollabOrgs);    
    
      
    //    result.add("CollaborationTypes");
    tempList = MyIsernModel.stringToArray(newEntry.get(2).trim());
    for (String item : tempList) {
      tempCollabTypes.getCollaborationType().add(item);
    }
    target.setCollaborationTypes(tempCollabTypes);
    

    tempList = MyIsernModel.stringToArray(newEntry.get(3).trim());
    for (String item : tempList) {
      tempYears.getYear().add(new BigInteger(item));
    }
    target.setYears(tempYears);
   
    //    result.add("Bio-Statement");
    tempList = MyIsernModel.stringToArray(newEntry.get(4).trim());
    for (String item : tempList) {
      tempOutcome.getOutcomeType().add(item);
    }
    target.setOutcomeTypes(tempOutcome);
    
    target.setDescription(newEntry.get(5).trim());

    return "";
  }
  

}
